/**
 * 
 */
package xyz.allin1.charlesloader;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
import java.util.*;

import javassist.*;






/**
 * @author iYoungDone
 *
 */
public class CharlesMonitorTransformer implements ClassFileTransformer {

    /**
     * 
     */
    public CharlesMonitorTransformer() {
        // TODO Auto-generated constructor stub
    }

    /* (non-Javadoc)
     * @see java.lang.instrument.ClassFileTransformer#transform(java.lang.ClassLoader, java.lang.String, java.lang.Class, java.security.ProtectionDomain, byte[])
     * public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte classfileBuffer[])
     */
    @Override
    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer)
            throws IllegalClassFormatException {
        // TODO Auto-generated method stub
        //System.out.println("(*^__^*) 变形金刚O(∩_∩)O~Transformer");
        //System.out.println("(*^__^*) Input Param className:"+className);
        className = className.replace("/", ".");
        CtClass ctClass = null;

        // if(!className.equals("com.xk72.charles.License"))
        //     return null;
        
       /* //// Version 4.1.1  21 April 2017
        if(!className.equals("com.xk72.charles.slZe"))
        {
            return null;
        }*/
        
        /*////  Version 4.1.2  13 May 2017
        if(!className.equals("com.xk72.charles.qFep"))
        {
            return null;
        }*/
        
        /*////  Version 4.1.3  20 June 2017
        if(!className.equals("com.xk72.charles.psPJ"))
        {
            return null;
        }*/
        
        /*////  Version 4.1.4  10 July 2017
        if(!className.equals("com.xk72.charles.gIbD"))
        {
            return null;
        }*/
        
        /*////Version 4.2  30 September 2017
        if(!className.equals("com.xk72.charles.WNzU"))
        {
            return null;
        }*/
        
        
        ////Version 4.2.8        28 February 2019
        if(!className.equals("com.xk72.charles.qHTb"))
        {
            return null;
        }
        
        
        
        ////调用堆栈跟踪注入代码
        Exception e1 = new Exception("---B.S.--- Exception ");
        e1.printStackTrace();

        try
        {
            System.out.println("(*^__^*) I Found className: " + className);

/*            //// 打印加载的这个类文件
            ByteArrayInputStream is = new ByteArrayInputStream(classfileBuffer);
            InputStreamReader input = new InputStreamReader(is);
            BufferedReader bf = new BufferedReader(input);
            String line = null;
            
            try {
                while((line=bf.readLine()) != null){
                    System.out.println(line);
                    }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            // 字节数组打印 
            System.out.println(Arrays.toString(classfileBuffer));
*/
            // 注意:以下语句不执行可能是javassist.jar没有一起打包进jar包文件
            // 获取默认类型池对象
            ClassPool classPool = ClassPool.getDefault();
            // 没有执行到这里,注意javassist.jar放在同CharlesLoader目录下
            //System.out.println("classPool: " + classPool);
           
            // 获取指定的类文件
            ctClass = classPool.makeClass(new ByteArrayInputStream(classfileBuffer));
            
//            System.out.println("ctClass: " + ctClass);
//            System.out.println("classfileBuffer length: " + classfileBuffer.length);
//            System.out.println("toString: " + classfileBuffer.toString());
//            System.out.println(ctClass.getName());  // 获取类名
//            System.out.println("\tpackage " + ctClass.getPackageName());  // 获取包名
//            System.out.print("\t" + Modifier.toString(ctClass.getModifiers()) + " class " + ctClass.getSimpleName());  // 获取限定符和简要类名
//            System.out.println(" extends " + ctClass.getSuperclass().getName());  // 获取超类

            /*// 参考的历史版本This is v4.0.2 key
            CtMethod a = ctClass.getDeclaredMethod("a", null);
            a.setBody("return true;");
            CtMethod ping = ctClass.getDeclaredMethod("b", null);
            ping.setBody("return \"qtfreet00 www.qtfreet.com\";");*/

            /*// Version 4.1.1  21 April 2017 key
            System.out.println("(*^__^*) I am Working......");
            CtMethod ctm1 = ctClass.getDeclaredMethod("RrCt", null);
            ctm1.setBody("return true;");
            System.out.println("(*^__^*) ctm1 Done.");
            CtMethod ctm2 = ctClass.getDeclaredMethod("Vvni", null);
            ctm2.setBody("return \"iYoungDone Coded by B.S.O.D."
            +"\\r\\n  www.appleos.xyz \\r\\n❤ thanks to javassist,rover12421,qtfreet00,Sound.\";");
            System.out.println("(*^__^*) ctm2 Done.");
            System.out.println("(*^__^*) All Done, Have Fun!!!");*/
            
            /*// Version 4.1.2  13 May 2017  key
            System.out.println("(*^__^*) I am Working......");
            CtMethod ctm1 = ctClass.getDeclaredMethod("gtOW", null);
            ctm1.setBody("return true;");
            System.out.println("(*^__^*) ctm1 Done.");
            CtMethod ctm2 = ctClass.getDeclaredMethod("SkgP", null);
            ctm2.setBody("return \"iYoungDone Coded by B.S."
            +"\\r\\n  www.appleos.xyz \\r\\n❤ thanks to javassist,rover12421,qtfreet00,Sound.\";");
            System.out.println("(*^__^*) ctm2 Done.");
            System.out.println("(*^__^*) All Done, Have Fun!!!");*/
            
            /*// Version 4.1.3  20 June 2017
            System.out.println("(*^__^*) I am Working......");
            CtMethod ctm1 = ctClass.getDeclaredMethod("qIvM", null);
            ctm1.setBody("return true;");
            System.out.println("(*^__^*) ctm1 Done.");
            
            //CtMethod ctm2 = ctClass.getDeclaredMethod("mLFE", null);
            //ctm2.setBody("");
            //System.out.println("(*^__^*) ctm2 Done.");
            
            CtMethod ctm3 = ctClass.getDeclaredMethod("tCiz", null);
            ctm3.setBody("return \"爱淫荡 Coded by B.S."
                    +"\\r\\n  www.appleos.xyz"
                    +"\\r\\n❤ thanks to javassist,rover12421,qtfreet00,Sound.\";");
            System.out.println("(*^__^*) ctm3 Done.");
            
            CtClass[] param_ctm4 = new CtClass[2];
            param_ctm4[0] = classPool.get(String.class.getName()) ;
            param_ctm4[1] = classPool.get("java.lang.String") ;
            CtMethod ctm4 = ctClass.getDeclaredMethod("qIvM", param_ctm4);
            ctm4.setBody("return null;");
            System.out.println("(*^__^*) ctm4 Done.");*/
            
            /*// Version 4.1.4  10 July 2017
            System.out.println("(*^__^*) I am Working......");
            CtMethod ctm1 = ctClass.getDeclaredMethod("xUFT", null);
            ctm1.setBody("return true;");
            System.out.println("(*^__^*) ctm1 Done.");
            
            //CtMethod ctm2 = ctClass.getDeclaredMethod("QNfW", null);
            //ctm2.setBody(" ");
            //System.out.println("(*^__^*) ctm2 Done.");
            
            CtMethod ctm3 = ctClass.getDeclaredMethod("PcqR", null);
            ctm3.setBody("return \"爱淫荡 Coded by B.S."
                    +"\\r\\n  www.appleos.xyz"
                    +"\\r\\n❤ thanks to javassist,rover12421,qtfreet00,Sound.\";");
            System.out.println("(*^__^*) ctm3 Done.");
            
            CtClass[] param_ctm4 = new CtClass[2];
            param_ctm4[0] = classPool.get(String.class.getName()) ;
            param_ctm4[1] = classPool.get("java.lang.String") ;
            CtMethod ctm4 = ctClass.getDeclaredMethod("xUFT", param_ctm4);
            ctm4.setBody("return null;");
            System.out.println("(*^__^*) ctm4 Done.");*/
            
            
            /*//Version 4.2  30 September 2017
            System.out.println("(*^__^*) I am Working......");
            CtMethod ctm1 = ctClass.getDeclaredMethod("OjEP", null);
            ctm1.setBody("return true;");
            System.out.println("(*^__^*) ctm1 Done.");
            
            //CtMethod ctm2 = ctClass.getDeclaredMethod("wfpb", null);
            //ctm2.setBody(" ");
            //System.out.println("(*^__^*) ctm2 Done.");
            
            CtMethod ctm3 = ctClass.getDeclaredMethod("DZZn", null);
            ctm3.setBody("return \" 爱淫荡 Coded by B.S."
                    +"\\r\\n  www.appleos.xyz"
                    +"\\r\\n❤ Thanks to javassist,rover12421,qtfreet00,Sound.\";");
            System.out.println("(*^__^*) ctm3 Done.");
            
            CtClass[] param_ctm4 = new CtClass[2];
            param_ctm4[0] = classPool.get(String.class.getName()) ;
            param_ctm4[1] = classPool.get("java.lang.String") ;
            CtMethod ctm4 = ctClass.getDeclaredMethod("OjEP", param_ctm4);
            ctm4.setBody("return null;");
            System.out.println("(*^__^*) ctm4 Done.");*/
            
            
            //Version 4.2.8            28 February 2019
            System.out.println("(*^__^*) I am Working......");
            CtMethod ctm1 = ctClass.getDeclaredMethod("DdNM", null);
            ctm1.setBody("return true;");
            System.out.println("(*^__^*) ctm1 Done.");
   
            CtMethod ctm3 = ctClass.getDeclaredMethod("gbef", null);
            ctm3.setBody("return \"爱淫荡 Coded by B.S. - Multi-Site License"
                    +"\\r\\n  www.appleos.xyz  Allin1.Xyz"
                    +"\\r\\n❤ Thanks to javassist,rover12421,qtfreet00,Sound.\";");
            System.out.println("(*^__^*) ctm3 Done.");
        
            ////
            System.out.println("(*^__^*) 爱淫荡.");
            System.out.println("(*^__^*) All Done, Have Fun!!!");
            
            ////只需要设置这一句就可以破解好的class类文件就会dump出来
            CtClass.debugDump = "./charles-bs-cr";

/*            ////把生成的class类文件写入文件导出破解好的class类文件  
            byte[] byteArr = ctClass.toBytecode();
            
            String pathString = "./com/xk72/charles";
            //String classNameString = "./qFep-bs.class";
            String classNameString = "qFep.class";
            
            File dir = new File(pathString);
            ////  递归创建目录
            if (dir.mkdirs())
            {
                System.out.println("Create Dir......succeeded."); 
            }
            
            File file = new File(pathString+"/"+classNameString);
            
             if(!file.exists())
             {
                 System.out.println("createNewFile......succeeded");
                 file.createNewFile();
             }
            
            FileOutputStream fos = new FileOutputStream(file);
            
            long begin = System.currentTimeMillis();
            
            fos.write(byteArr);

            long end = System.currentTimeMillis();   

            System.out.println("FileOutputStream.write 执行耗时: " + (end - begin) +"毫秒"); 
            
            fos.close();
*/            

            return ctClass.toBytecode();
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        return new byte[0];
    
        //return null;
    }

}
